package net.vz.geoapi;

import java.io.UnsupportedEncodingException;
import java.util.Map;

import net.vz.geoapi.utils.GeoApiInputException;
import net.vz.geoapi.utils.GeoProxy;

/**
 * abstract search class
 * provides general search methods for subclasses
 * 
 * @author sirrgang
 * 
 */
public abstract class GeneralSearch {

    private static String BASE_URL = "http://api.geoapi.com/";
    protected static String DEFAULT_VERSION = "v1";
    
    //allowed type values
    public static String SEARCH_TYPE_BUSINESS     = "business";
    public static String SEARCH_TYPE_POI          = "POI";
    public static String SEARCH_TYPE_INTERSECTION = "intersection";
    public static String SEARCH_TYPE_NEIGHBORHOOD = "neighborhood";
    public static String SEARCH_TYPE_CITY         = "city";
    public static String SEARCH_TYPE_USER_ENTITY  = "user-entity";
    
    private String type; //Allowed values are business, POI, intersection, neighborhood, city, and user-entity
	private int limit;
	private int includeParents;
	private String apiKey;
	private int prettyJsonEnabled;
	private String version = null;
	
	public GeneralSearch(String _apiKey, String _version) {
	    this.apiKey  = _apiKey;
	    this.version = _version; 
	}
	
	/**
	 * get url search method
	 * @return string method name
	 */
	protected abstract String getSearchMethod();
	
	/**
	 * returns request parameter as map
	 * @return map<string, string>
	 */
	protected abstract Map<String, String> getRequestParams();
	
	protected String getApiKey() {
	    return this.apiKey;
	}
	
	public void setLimit(int _limit) {
	    this.limit = _limit;
	}
	
	public void setIncludeParents(boolean _flag) {
	    this.includeParents = _flag ? 1 : 0;
	}
	
	public void setType(String _type) {
        this.type = _type;
    }
	
	public String getType() {
	    return this.type;
	}
	
	public int getLimit() {
	    return this.limit;
	}
	
	/**
     * validates input parameters
     * @throws GeoApiInputException
     */
    protected void validateInput() throws GeoApiInputException {
        if (this.apiKey == null || this.apiKey.length() == 0) {
            throw new GeoApiInputException();
        }
    }
    
	public void enablePrettyOutput(boolean _flag) {
	    this.prettyJsonEnabled = _flag ? 1 : 0;
	}
	
	/**
	 * request method to get data from geoapi service
	 * @return json response
	 */
	public String doRequest() throws GeoApiInputException {
	    String url = BASE_URL + this.version + "/" + this.getSearchMethod();
	    Map<String, String> params;
	    
	    //check for input errors
	    this.validateInput();
	    
	    params = this.getRequestParams();
	    params.put("apikey", this.apiKey);
	    params.put("pretty", String.valueOf(this.prettyJsonEnabled));
	    params.put("limit", String.valueOf(this.limit));
	    params.put("include_parents", String.valueOf(this.includeParents));
	    
	    try {
            String response = GeoProxy.sendGetRequest(url, GeoProxy.getUrlEncodedParams(params));
            return response;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
	}
}
